home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
PROGRAMM
/
PASCAL
/
0191.ZIP
/
PGM-AIDE.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1985-11-03
|
33KB
|
586 lines
{$C-}
{-----------------------------------------------------------------------------}
{ }
{ }
{ " S o r r y , D a v e, I C a n ' t D o T h a t . " }
{ }
{ Arthur C. Clark }
{ " 2 0 0 1 " }
{-----------------------------------------------------------------------------}
{ Stayres Version 3.31
{ A Turbo "stay-resident" program clobbers the Dos register stack. It
jumps over the Turbo run-time initialization code that would set up the
program registers and environment. Secondly, a stay-resident program
could not ordinarily issue file I/O since that would clobber Dos interrupt
registers. Therefore, the following code proposes an inline solution,
providing a Turbo entry stack for "stay-resident" programs and allowing
those programs to issue Dos I/O and other interrupts.
This Turbo stay-resident demo has been put together to perform both Dos I/O
and Bios interrupts. It has been tested for re-entrancy and recursiveness
on an IBM PC with PCDOS 2.1, 3.1 .
R_U_N I_N_S_T_R_U_C_T_I_O_N_S
Separate the include files, compile to a COM file using STAYRES.??? as the
Main file. Then execute the command file and activate with the default
Alt-F10 key. It will also free its memory and return to Dos with the
Ctrl-Home key at the last "Press a key" prompt (Illustrated in the Stayxit
file). Maximum free dynamic memory should be between 300-400 paragraphs
since this demo uses a recursive stack. If you get $FF runtine errors or
"allocation error", "cannot load Command.Com", then raised the mAximum
free value to something reasonable but less than your maximum memory -
20K. This program can ONLY run as a COM file.
For those of you already using user interrupts 60-67, please change the
User_Int constant to an interrupt number you do not currently use .
The Hunter's Helper
Lane Ferris
4268 26th St
San Francisco,Ca. 94131
[ 70357,2716 ]
}
{-----------------------------------------------------------------------------}
{ This code has been tested/used on an IBM PC using PC-DOS 2.10/3.1 }
{-----------------------------------------------------------------------------}
{ Authors: Lane H. Ferris (Stay Resident/Exit Code) }
{ Neil J. Rubenking (Directory code and ideas) }
{ Other Public Gurus on whose shoulders we stand.}
{
PURPOSE: This code will serve as a template to create other "Stay Resident"
programs in Turbo Pascal(tm). This code intercepts Int 16,
displacing original Interrupt 16 Vector to User Interrupt 60.
During execution of other programs, it can be invoked by the
special key combination specified by "Our_Char" (in this case
Alt-F10.)
Modifications:
7. 7.85 - Replace Windows with a more simple form/less code.
7. 8.85 - Replace Window Array with Pointers/Heap form.
7.11.85 - Re-issue termination Keyboard Read / pass back to user
Would like to back up Instruction Ptr by two bytes before
the Int 16 ($CD16) but it might be a "long call" by
some other Kbd interceptor (chirp chirp chrip)... and
thats "trouble in River City".
7.19.85 - Clean up RmWin "incorrect" attribute bugs. If screen
isnt cleared, we get border attribute, not text attrb.
- Remove last window at Termination Time (Ctrl-Home).
8.26.85 - Version 3.10 Changes
1) Save 40 words in StaySave/Rstr to avoid clobbering
Dos Stack when entering Dos with Turbo Write(ln) caused
by Int 21 Function 5 (Writln(Lst,..)) which re-issues
Int 16.
2) Change Int 68 to Int 67 to Avoid collisions with
Dos 3.1 on an AT.
3) Correct "Press a Key..." to accept any "Key..."
(not just Cr).
4) Check Int16 function. Jmp directly to Int16 if not
a character request. Avoids 40 word Save/Restore
overhead.
9.04.85 - Version 3.20 changes
When returning to user program, pass back a fake
"Ctrl-key" scan code to allow immediate re-execution
of the TSR (Terminate Stay Resident) program. Also
solves SideKick incessant bird caws.
9.18.85 - Version 3.2C
When saving/restoring the stack, save 40 words or less
depending on stack size (0-Sp = stack size) to avoid
overflowing into SS:0 when stack is less than 40 words.
Put back the "wait for user key logic" at Demo end.
Beep like SuperKick if Key is OurKey
Version 3.31
9.19.85 Futz around with the "wait for user key logic", allow
the Our_key to pass, but beep user to show we aint
gonna activate, cuz our InUse bit is still set.
Clean up the documentation and duplicate instructions in
StaySave/Rstr.
Change Int67 to Int60 for Fun and Profit and get around
Mark Stanock's use of those locations.
}
Program Stay_Resident;
{ * * * * * * * CONSTANTS * * * * * * * * * * * * * * * * * * * * * * }
const
Our_Char = 104; {this is the scan code for AltF1}
Ctrl_Home = #119; {Control Home Scan Code }
Quit_Key = #119;
Ctrl_End = #117; {Control End Scan Code }
User_Int = $60; {place to put new interrupt}
Kybrd_Int = $16; {BIOS keyboard interrupt}
MaxWin = 3; { Max number of windows open at one time }
{ - - - - - - T Y P E D E C L A R A T I O N S - - - - - - - - - - - - }
Type
Regtype = record Ax,Bx,Cx,Dx,Bp,Si,Di,Ds,Es,Flags:integer end;
HalfRegtype = record Al,Ah,Bl,Bh,Cl,Ch,Dl,Dh:byte end;
filename_type = string[64];
{ - - - - - - - T Y P E D C O N S T A N T S - - - - - - - - - - - - - - -}
Const
{regs is defined as a typed constant in order to get it in the code segment}
Regs : regtype = (Ax:0;Bx:0;Cx:0;Dx:0;Bp:0;Si:0;Di:0;Ds:0;Es:0;Flags:0);
OurDseg: integer = 0; {Our Data Segment Value }
OurSseg: integer = 0; {Our Stack Segment Value }
DosSseg: integer = 0; {Dos Stack Segment Value }
Inuse : Boolean = false; {Recursion flag }
{ The following two constants *MUST* remain in the Ip:CS order }
{ because StaySave uses them as a JMP target }
User_IntIP : integer = 0; {Pointer to Original IP Int value }
User_IntCs : integer = 0; {Pointer to Original Cs Int value }
StackSize : integer = 0; {Current User/or Dos Stack word size}
{ - - - - - - - V A R I A B L E S - - - - - - - - - - - - - - - - - - - - - -}
Var
SaveRegs : regtype;
HalfRegs : halfregtype absolute regs;
Terminate_flag : boolean ;
Keychr : char ;
Old_Xpos,Old_Ypos : integer ;
{-----------------------------------------------------------------------------}
{ W I N D O W R O U T I N E }
{---------------------------------------------------------------------------- }
{$I WINDO.INC}
{-----------------------------------------------------------------------------}
{ S T A Y E X I T }
{-----------------------------------------------------------------------------}
{$I STAYXIT.320}
{----------------------------------------------------------------------}
{ B e e p : S o u n d t h e H o r n }
{----------------------------------------------------------------------}
Procedure Beep(N :integer); {------------------------------------------}
Begin { This routine sounds a tone of frequency }
Sound(n); { N for approximately 100 ms }
Delay(100); {------------------------------------------}
Sound(n div 2);
Delay(100);
Nosound;
End {Beep} ;
{-----------------------------------------------------------------------------}
{ THE FOLLOWING ARE THE USER INCLUDE ROUTINES }
{-----------------------------------------------------------------------------}
{-----------------------------------------------------------------------------}
{ E P S O N P R I N T E R S E T U P }
{-----------------------------------------------------------------------------}
Procedure EP;
{$I EP.INC}
{-----------------------------------------------------------------------------}
{ S C R E E N C O U N T E R }
{-----------------------------------------------------------------------------}
Procedure SC;
{$I SC.INC}
{-----------------------------------------------------------------------------}
{ P R O G R A M A I D E }
{-----------------------------------------------------------------------------}
Procedure PgmAide;
{$I PGM-AIDE.DVR}
{-----------------------------------------------------------------------------}
{ THE ABOVE ARE THE USER INCLUDE ROUTINES }
{-----------------------------------------------------------------------------}{---------------------------------------------
{-----------------------------------------------------------------------------}
{ P R O C E S S I N T E R R U P T }
{ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - }
Procedure Process_Intr;
{ PURPOSE: This procedure replaces the standard keyboard interrupt. If
anything but <Alt>-F1 is pressed, the key is passed on to the
standard keyboard interrupt. B*U*T when <Alt>- F1 is pressed,
this program takes over. The variable InUse is set to TRUE to
ensure that this code doesn't try to run "on top of itself " AND to
indicate to the Inline code to save/restore the original interrupt
regs.
}
Begin
{ K e y b o a r d Interrupt o c c u r s here }
{----------------------------------------------------------------------}
{ This could also have the include data as $I StaySave.331 }
{****************************************************************************}
{ S T A Y S A V E . I N C }
{ }
{ This is the Staysave.Inc file included above }
{ }
{ Separate the code out into a file or replace the $I Staysave.331 }
{ statement above with this code. }
{****************************************************************************}
{This Inline routine will save the regs and Stack for Stay resident programs.
It restores DS and SS from the previously saved integer constants "OurDseg"
and "OurSSeg". This is important since Dos is not re-entrant and any attempt
to use Interrupt I/O services will clobber the very stack on which the
Resident Turbo program just saved its regs. Thus, on the final return, you
and Toto will end up somewhere other than Kansas and without your Ruby Reds.
}
{ Arthor: Lane Ferris
- The Hunter's Helper -
Distributed to the Public Domain for use without profit.
Original Version 5.15.85
}
{ On entry the Stack will already contain: }
{ 1) Sp for Dos }
{ 2) Bp for Dos }
{ 3) Ip for Dos }
{ 4) Cs for Dos }
{ 5) Flags for Dos }
Inline (
{ The following routine avoids the overhead of saving the DOS stack }
{ when the INT 16 function was not for a character request. This happens }
{ often (every four chars) as DOS checks on ^S/^Q/^C/Keypressed ad.nausea }
$80/$FC/$00/ {Cmp Ah,00 If Char request, }
$74/$07/ {Je ChrRqst enter Staysave code }
$5D/$5D/ {Pop Bp/Pop Bp else Restore Bp & }
$2E/ { Jump to Original Dos Interrupt }
$FF/$2E/User_IntIP/ {Jmp Far Cs:[User_IntIp] }
{ Move the current active registers to a save place}
{ChrRqst: }
$FA / {Cli Stop all interrupts }
{ Bp and Sp aready saved at Begin Stmt }
$55/ {Push Bp Save again for Regpak }
$BD/Regs/ {Mov Bp,offset REGS address savearea}
$2E/$89/$46/$00/ {CS:Mov [Bp+0],AX Save Users Registers }
$2E/$89/$5E/$02/ {Cs:Mov [Bp+2],Bx}
$2E/$89/$4E/$04/ {CS:Mov [Bp+4],CX}
$2E/$89/$56/$06/ {CS:Mov [Bp+6],DX}
$2E/$8F/$46/$08/ {Pop Cs:[Bp+8] Fetch Bp from stack }
$2E/$89/$76/$0A/ {CS:Mov [Bp+A],SI}
$2E/$89/$7E/$0C/ {CS:Mov [Bp+C],DI}
$2E/$8C/$5E/$0E/ {CS:Mov [Bp+E],DS}
$2E/$8C/$46/$10/ {CS:Mov [Bp+10],ES}
$9C/ {PUSHF put Flags on stack to retrieve }
$2E/$8F/$46/$12/ {POP Cs:[Bp+12]}
{ If Current SS := [OurSseg] or (Inuse = True), }
{ then dont overlay the previously saved stack. }
{ This program is being recursive. }
$2E/$80/$3E/Inuse/$01/ {Cmp Cs:[Inuse],1 Inuse = True ? }
$74/$62/ {Je ReCurin Yes, -J-U-M-P- }
{ Switch the SS:Sp reg pair over to ES:Si }
{ Put Turbo's Stack pointers into SS:Sp }
$2E/$8C/$16/DosSSeg/ {Mov Cs:DosSSeg,SS Save Dos Stack Segment }
$8C/$D6/ {Mov Si,SS Es gets Dos stack }
$8E/$C6/ {Mov Es,Si }
$2E/$8E/$16/OurSSeg/ {Mov SS,Cs:OurSSeg SS Gets our Stack segment }
$2E/$8E/$1E/OurDseg/ {Mov Ds,Cs:Our_Ds DS Gets our Data Segment }
{ If ES:Si (stack ptr) <> OurSSeg then }
{ Sp := Virgin Turbo Stack pointer. }
{ If Es:Si := OurSSeg, then this is a Read or }
{ Write before Inuse was set True. Dont clobber }
{ the current setting of Turbo stack pointer. }
$2E/$3B/$36/OurSSeg/ {Cmp Si,Cs:OurSSeg If SS := OurSSeg then }
$89/$E6/ {Mov Si,Sp dont clobber saved regs }
$74/$05/ {Je $+5 else get virgin stack ptr }
$3E/$8B/$36/$74/$01/ {Mov Si,Ds:[174] ..(cf. code at B2B 3.0x) }
$87/$F4/ {Xchg Sp,Si Set new Stack Pointer }
{ Stack Dos/User interrupted pgm regs for Exit. }
{ These are the original interrupt process regs }
{ that must be returned on interrupt return }
$2E/$FF/$76/$00/ {Push [Bp+0] Save Ax }
$2E/$FF/$76/$02/ {Push [Bp+2] Save Bx }
$2E/$FF/$76/$04/ {Push [Bp+4] Save Cx }
$2E/$FF/$76/$06/ {Push [Bp+6] Save Dx }
{Push [Bp+8] Save Bp }
$2E/$FF/$76/$0A/ {Push [Bp+A] Save Si }
$2E/$FF/$76/$0C/ {Push [Bp+C] Save Di }
$2E/$FF/$76/$0E/ {Push [Bp+E] Save Ds }
$2E/$FF/$76/$10/ {Push [Bp+10] Save Es }
{ Now stack the lesser of current stack size or }
{ 40 Words to our stack, to be re-stack on the }
{ interrupted pgms stack on exit. This is done }
{ to allow recursive entry into Dos/or other non }
{ re-entrant pgms. }
$29/$C9/ {Sub Cx,Cx Find minimum of current stack }
$29/$F1/ {Sub Cx,Si size or 40 words to save. }
$D1/$E9/ {Shr Cx,1 Stackbytes/2 for words. }
$83/$F9/$40/ {Cmp Cx,+40 This keeps up from overrunning }
$7E/$03/ {Jle $+3 the Stack Segment when it is less}
$B9/$40/$00/ {Mov Cx,40 than Dos stack size }
$2E/$89/$0E/StackSize/ {Mov Cs:StackSize,Cx Save current stack size }
{Restack:}
$26/$FF/$34/ {Push Es:[Si] Our Stack := Dos Es:Si }
$46/$46/ {Inc Si/Inc Si Get Next Dos Stack Word }
$E2/$F9/ {Loop to Restack }
$56/ {Push Si Save bottom of Dos Stack }
$2E/$8C/$5E/$0E/ {Mov Cs:[Bp+E],Ds Set New Data Segmt in regs}
{Recurin} { Jump here if Recursion }
$FB {Sti Enable Interrupts }
) ;
{...........................................................................}
{---------------------------------------------------------------------------}
{ END OF THE STAYSAVE REGISTER ROUTINE }
{---------------------------------------------------------------------------}
{ Set New Data Segmt in regs}
{----------------------------------------------------------------------}
{ Check the Int 16 request function in Ah reg:
0 = read character from Keyboard
1 = check character available
2 = check shift key values
}
{ HalfRegs.Ah = 0 This is a Character Request because StaySave }
{ doesnt allow an enter here unless it is! }
Intr (User_Int, Regs); { Use the DOS replaced interrupt}
{ Get Key from Keyboard }
If (Halfregs.Ah = Our_Char) { Separate the tests so code }
{ performs efficiently. }
then if (not InUse) then { Must be OUR key and not busy }
Begin { PROGRAM AIDE }
InUse := true; { "dont clobber saved stack"}
{--------------------------------------------------------------------------}
{ INVOKE USER PROCEDURE HERE }
{--------------------------------------------------------------------------}
PgmAide;
{--------------------------------------------------------------------------}
{ END USER PROCEDURE HERE }
{--------------------------------------------------------------------------}
While (not Keypressed); { Get input key for the users }
SaveRegs.Ax := 0 ; { interrupted program }
Intr(User_Int,SaveRegs); { Get the Scancode }
Regs.Ax := SaveRegs.Ax;
If HalfRegs.Ah = Our_Char then Beep(650);
InUse := false; { ok to restore interrupted stack }
End; { PROGRAM AIDE }
{---------------------------------------------------------------------------}
{---------------------------------------------------------------------------}
{ BEGINNING OF THE STAYRSTR ROUTINE }
{---------------------------------------------------------------------------}
{ This could also be used as $I StayRstr.331 }
{****************************************************************************}
{ S T A Y R S T R . I N C }
{ }
{ This is the StayRstr.Inc file included above }
{ Separate the code out into a file or replace the $I StayRstr.331 }
{ statement above with this code. }
{****************************************************************************}
{Version 3.31}
{ Inline Code to restore the stack and regs moved}
{ to the Turbo Resident Stack which allows }
{ re-entrancy into Dos for I/O and recursion }
{ for Turbo Terminate & Stay Resident programs. }
{ Author: Lane Ferris }
{ - The Hunter's Helper - }
{ Distributed to the Public Domain for use without profit. }
{ Original Version 5.15.85 }
{----------------------------------------------------------------------}
{ Restore the Dos (or interrupted pgm) Regs and Stack }
{----------------------------------------------------------------------}
{ On entry the Stack will already contain: }
{ Pointer to bottom of stack }
{ Bottom of Dos Stack Ptr }
{ StackSize words of saved pgm stack }
{ Dos Flags }
{ Dos Code Segment }
{ Dos Instruction Ptr }
{ Dos Base Pointer }
{ Dos Original Stack Ptr }
{ Retrieve the Regpack registers as they were }
{ stored for the Interrupt Entry. }
inline(
$BD/Regs/ {Mov Bp,offset REGS}
$2E/$8B/$46/$00/ {CS:Mov Ax,[Bp+0]}
$2E/$8B/$5E/$02/ {Cs:Mov Bx,[Bp+2]}
$2E/$8B/$4E/$04/ {CS:Mov Cx,[Bp+4]}
$2E/$8B/$56/$06/ {CS:Mov Dx,[Bp+6]}
$2E/$8B/$76/$0A/ {CS:Mov Si,[Bp+A]}
$2E/$8B/$7E/$0C/ {CS:Mov Di,[Bp+C]}
$2E/$8E/$5E/$0E/ {CS:Mov DS,[Bp+E]}
$2E/$8E/$46/$10/ {CS:Mov ES,[Bp+10]}
$2E/$FF/$76/$12/ {Push Cs:[Bp+12] }
{PopF }
{ The following code was added to avoid }
{ the 80286 Pop flag (POPF) bug which }
{ enables interrupts while we are trying}
{ to POP the stack on odd byte boundry }
$EB/$01/ {JMP $+3 Skip over IRET }
$CF/ {IRET POP IP/CS/Flags }
$0E/ {PUSH CS Make a return }
$E8/$FB/$FF/ {CALL CS:$-2 Pop the Flags}
{ If [Cs:InUse]:= True, then dont restore the stack.}
{ This program is being recursive. Else restore Dos }
{ Stack and Program Entry registers for final exit. }
$2E/$80/$3E/Inuse/$01/ {Cmp byte ptr Cs:[Inuse],1 }
$74/$25/ {Je ReCurOut J-U-M-P }
{ Move "StackSize" words back to the interrupted pgms}
{ stack. The originals could have been clobber by our}
{ being recursive. (Especially true of DOS) }
$FA / { Cli ; Stop all interrupts }
$5E/ {Pop Si Bottom of Dos Stack }
$2E/$8B/$0E/StackSize/ {Mov Cx,Cs:StackSize Saved Stack Words }
$2E/$8E/$06/DosSSeg/ {Mov ES,Cs:DosSSeg Get Dos StackSegment }
{Restack:}
$4E/$4E/ {Dec Si/Dec Si Backup Dos Stack }
$26/$8F/$04/ {Pop Es:[Si] Dos Stack := Our Stack }
$E2/$F9/ {Loop to Restack }
$89/$F5/ {Mov Bp,Si Save Dos Sp across Pops }
{ - C - A - U - T - I - O - N - }
{ Restore the original interrupted programs regs }
{ except Ax. Ax usually contains status. It contains }
{ a scan code and key for Int 16. You may want to }
{ rework this if using another interrupt. }
$07/ {Pop Es }
$1F/ {Pop Ds }
$5F/ {Pop Di }
$5E/ {Pop Si }
$5A/ {Pop Dx }
$59/ {Pop Cx }
$5B/ {Pop Bx }
$44/$44/ {Inc sp/Inc sp Thow old Ax value away }
$89/$EC/ {Mov Sp,Bp Setup Dos Stack Ptr }
$2E/$8E/$16/DosSSeg/ {Mov SS,Cs:DosSSeg Give back Dos Stack }
{RecurOut} {Clean up the Stack }
$5D/ {Pop Bp Throw away old dos Sp }
$BD/Regs/ {Mov Bp,offset REGS }
$2E/$FF/$76/$12/ {Push Cs:[Bp+12] Flags from last }
{PopF interrupt. }
{ The following code was added to avoid }
{ the 80286 Pop flag (POPF) bug which }
{ enables interrupts while we are trying }
{ to POP the stack on odd byte boundry }
$EB/$01/ {JMP $+3 Skip over IRET }
$CF/ {IRET POP IP/CS/Flags }
$0E/ {PUSH CS Make a return }
$E8/$FB/$FF/ {CALL CS:$-2 Pop the Flags}
$5D/ {Pop Bp Retrieve old BP }
$FB/ {Sti Enable interrupts }
$CA/$02/$00 {Ret Far 002 Thow old flags away}
);
{.......................................................................}
{---------------------------------------------------------------------------}
{ END OF THE STAYRSTR ROUTINE }
{---------------------------------------------------------------------------}
End ;{Process_Intr}
{-----------------------------------------------------------------------}
{-------------------------------------------------------------------------}
{ M A I N }
{-------------------------------------------------------------------------}
{ The main program installs the new interrupt routine }
{ and makes it permanently resident as the keyboard }
{ interrupt. The old keyboard interrupt is addressed }
{ through #60H, so it can still be used. }
{ }
{ The following dos calls are used: }
{ Function 25 - Install interrupt address }
{ input al = int number, }
{ ds:dx = address to install }
{ Function 35 - get interrupt address }
{ input al = int number }
{ output es:bx = address in interrupt }
{ Function 31 - terminate and stay resident }
{ input dx = size of resident program }
{ obtained from the memory }
{ allocation block at [Cs:0 - $10 + 3] }
{ Function 49 - Free Allocated Memory }
{ input Es = Block Segment to free }
{ Interrupt 20 - Return to invoking process }
{-----------------------------------------------------}
{-----------M A I N B L O C K---------------------------------------------}
Begin {**main**}
InUse := false;
OurDseg:= Dseg; { Save the Data Segment Address for Interrupts }
OurSseg:= Sseg; { Save our Stack Segment for Interrupts }
Terminate_Flag := false ;
SaveRegs.Es := 00; { clear for Dos 3.0 bug }
{now install the interrupt routine}
SaveRegs.Ax := $3500 + User_Int;
Intr($21,SaveRegs); {Check to make sure int not already used}
if SaveRegs.Es <> $00 then
WriteLn ('Interrupt in use -- can''t install Resident Turbo Code')
else
begin
SaveRegs.Ax := $3500 + Kybrd_Int;
Intr($21,SaveRegs); {get the address of keyboard interrupt }
SaveRegs.Ax := $2500 + User_Int;
SaveRegs.Ds := SaveRegs.Es;
SaveRegs.Dx := SaveRegs.Bx;
Intr($21,SaveRegs); { set the user-interrupt address to point
{ to the keyboard interrupt address }
SaveRegs.Ax := $2500 + Kybrd_Int;
SaveRegs.Ds := Cseg;
SaveRegs.Dx := Ofs(Process_Intr);
Intr ($21,SaveRegs); { set the keyboard interrupt to point to
"Process-Intr" above}
User_IntIp := MemW[0:User_Int * 4 ]; { Location of User Interrupt Ip }
User_IntCs := MemW[0:User_Int * 4 +2];{ Location of User Interrupt Cs }
{----------------------------------------------------------------------------}
{ INITIALIZE YOUR PROGRAM HERE }
{----------------------------------------------------------------------------}
{ Initialize Your Progam Here since you wont get control again
until "Our_Char" is entered from the Keyboard. }
Writeln(' Turbo Stay-Resident Program Aide');
Writeln(' Press Alt-F1 to Call');
{----------------------------------------------------------------------------}
{ END OF INITALIZE PROGRAM CODE }
{----------------------------------------------------------------------------}
{now terminate and stay resident}
{ Pass return code of zero }
SaveRegs.Ax := $3100 + 0 ; { Terminate and Stay Resident }
SaveRegs.Dx := MemW [Cseg-1:0003] ; { Prog_Size from Allocation Blk}
Intr ($21,SaveRegs);
end;
{ END OF RESIDENCY CODE }
end.